// ?????? ?????????? ????????? ???? ?? ??????????? ????? ?????
// ?????? ??????????????? ????????? ?????????? ? ?????????? ?? ? ????? ???????
// ??????? ??????. ?????: PE_Kill
//----------------------------------------------------------------------------------
var call_VM
var call_cur
//----------------------------------------------------------------------------------
var scan_start
var scan_end
//----------------------------------------------------------------------------------
var base_old
var base_new
//----------------------------------------------------------------------------------
var table_of_jcc
var table_of_jcc_base
var type_of_jcc
//----------------------------------------------------------------------------------
var emule_swich
var emule_last_jamp

var emule_type_jcc_temp
var emule_jcc_temp

var emule_type_jcc
var emule_jcc

var emule_cmp_size
var emule_cmp_get_arg1
var arg1_num
var arg1_display

var emule_cmp_get_arg2
var arg2_num
var arg2_display

var emule_type_cmp
var type_of_cmp
var emule_cmp

var emule_cmp_jcc
var emule_cmp_type_jcc
//----------------------------------------------------------------------------------
var str1
var str2
var str3
//----------------------------------------------------------------------------------
var oep
var temp
var Info
var addr_cur
var iter
var trace_call
//----------------------------------------------------------------------------------
log ""
log "____________________________________"
log ""
log "Virtual Machine Rebuilder by PE_Kill"
log "____________________________________"
log ""
log "Inicialize..."
//jmp @init_hand
  ////////////////////////////////////////////////////////////////////////////////////////
  // ????????????? ???????								//
  ////////////////////////////////////////////////////////////////////////////////////////
mov oep,eip			// ????????? eip ??? ???????????? ??????????????
mov addr_cur,eip		// ???????? ??????? eip
and addr_cur,FFFFF000		// ??????????? ?? 1000h
mov eip,addr_cur		// ????????? ?? ???????????? ?????
mov scan_start,eip		//!??????? ????? ?????? ????? ????? ????????? ???????? ????????????
mov base_old,eip		//!??????? ????? ????? ????? ????? ???????? ????
  //====================================================================================//
  // ???? ?????? ?????, ???????? ? VM. ????????????? ???????????? ?????? ????? ???????? //
  // ??, ??? ?? ???????? ?? 1000h. ?? ?? ??? ??????????????.				//
  //====================================================================================//
@init_find_VM_call:		
  find addr_cur,#E8#		// ???? ????? "call"
    cmp $RESULT,0		// ????? ??? ???????
    je ERR_VM_CALL_NOT_FOUND	// ??? :( ???????????? ????? ??? ?????????? :( ??????? ?????? ? ??????
  mov addr_cur,$RESULT		// ??! ??????? ???????? ????? ? ??????????
  inc addr_cur			// ??????? ????????? ??????????????? ?? ????? ????? VM (??????????? E8)
  mov call_VM,[addr_cur]	// ??????? ? ?????????? ???????? ????? VM
  add call_VM,addr_cur		// ????????? ?????????? ????? call_VM
  add call_VM,4			//!????????????? ???????????? ???????? ?????.
  mov call_cur,call_VM		// ??????????? ?????? ??????????. ??? ????????? ?????????? ??? ????????? ???????
  and call_cur,00000FFF		// ???????? ?????? 5 ????. ???????? ???????????? ?????
  cmp call_cur,00000000		// ???? ?? ???????? ?? 1000h ????, ?? ????? ???? ???????, ??? ??? ??? call_VM
jne @init_find_VM_call		// ????? ????????? ?????
//end @init_find_VM_call
  //====================================================================================//
dec addr_cur			// ??????? ????????? ?? ?????? call_VM
mov eip,addr_cur		// ?????? ?? ???????? ?????  call_VM
inc addr_cur			// ??????????? ????????? ?? ??????, ???? ??? ?? call_VM ? ???????? ?????????? ?????
mov trace_call,eip		// ?????????? ??????? ????? ??? ??????????? ???????????
sti				// Step into. ??????? ? ???????? ????.
//======================================================================================//
// call_VM ????? ? ??????? ??????, ??? ??????????? ????????????? ?????? ????? ?????????.//
// ??? ??? ??????? ?? ?????, ?? ????? ??? ???? ?????? ?? ?????? ????? VM. ??? ????? 	//
// ?????? ????? VM ??? ? ???? ????????. ??? ????? ????? ???????????? ?? ??? ???, ????	//
// ?? ?????? ? ????? ???? ???? (?? ?????????? ????) ???? ???? ??????? ???????? ?? ??????//
// ?????? 300h (????? ??? ?? VM)							//
//======================================================================================//
mov iter,0			// ???????? ???????
@init_trace_prefix:		
  inc iter			// ????????? ?? 1
  cmp iter,300			// ??? 300-? ?????????
  je @init_find_VM_call		// ??, ???????? ??? ???????.
//!![ ?????, ????? ?? ???????? ?????? ??????? ??????????? ? ????????? ?????????? ]!!//
//!![ ????????? ???????, ??? ??? ??????? ????????? ???????? ??? ?? ?????.	 ]!!//
  mov call_cur,eip		// ?????????? ??????? ?????
  sti				// ?????? ???? ???
  mov temp,[esp]		// ???????? ??????? ???????? ?????
  sub temp,2			// ???????? 2, ????, ? ??????? ?? ?????? ?????: call exx, ?.?. 2 ?????
  cmp temp,call_cur		// ?????????? ??????????? ????? ? ?????????????? ??????? ????????-2
jne @init_trace_prefix		// ?? ?????? ?????? ?? ??? ? ??????? ?????????????
//and @init_trace_prefix
//======================================================================================//

//======================================================================================//
// ? ???? ??????? ????? ?????????? ????????????? ??????, ????????? ????? ? ??????,	//
// ?? ???????????? ??? ??????. ?? ????? ?? ?? ???? ??????? ?????????? ????????? ??? 	//
// ??????????????? ? ???? ??????????? ??????. ??????? ?????????????? ????????? ??????	//
// ????? ???????? ?????. ???? ???? ?? ????? ??????, ???? ?????? ?????? 111, ? ??????? ?	//
// ???? VM ????????? ???? ???? ?????, ????????? ??????. ??? ? ????? ??????.		//
//======================================================================================//
mov iter,eip			// ?????????? eip
mov addr_cur,eip		// ?????????? eip
@init_find_error111:		// ???? ????, ???????? ?????? 111
  find addr_cur,#68#		// ???? PUSH XXXXXXXX
    cmp $RESULT,0		// ?? ???????
    je @ERR_INIT_FAILED		// ??????? ?????? ? ??????
  mov addr_cur,$RESULT		// ???????? ????? ????????? PUSH'a
  inc addr_cur			// ??????????? ????? PUSH
  mov call_cur,[addr_cur]	// ????????, ????????, ??????? ????????? ? ????
  mov temp,[call_cur]		// ???? ??? ??, ??? ?? ????, ?? ??? ????????? ?? ?????? "111"
  cmp temp,0D313131		// ?????????, ??? ?? ???
jne @init_find_error111		// ???, ??? ?? ?????????, ???? ??????
//end @init_find_error111

@init_find_emulate_instr:	// ?????? ????? ??????????? ?????, ???? ?? ?????? ????? call
  dec addr_cur			// ??? ?? ?????? ?? ??????, ? ???????? ?????? ?????? (????? ?????)
  cmp addr_cur,iter		// ?????????, ?? ????? ?? ?? ??????, ?????? ??????
  je @ERR_INIT_FAILED		// ???? ??, ??????? ?????? ? ??????
  mov temp,[addr_cur]		// ????????, ?? ??? ?????
  and temp,FF000000		// ???????? ??? ?????, ????? ???????
  cmp temp,E8000000		// ?????????? ?????? ???? ? ??????? call
jne @init_find_emulate_instr	// ???? ?? ?????, ????????? ?????
//end @init_find_emulate_instr
add addr_cur,3			// ???????????? ????????? ?? ????
bp addr_cur			// ?????? ???? ?? ????? ????????? ?????
run				// ????????? ?????????
bc addr_cur			// ??????????? ? ??????? ????
cmp eip,addr_cur		// ????????? ????????? ?? ????????????
  jne @ERR_INIT_FAILED		// ???? ???, ??????? ?????? ? ??????
sti				// Step into. ?????? ? ????.
//======================================================================================//

//======================================================================================//
// ???? ??????????:									//
// SUB AL,2										//
// JB SHORT ????????									//
// JE SHORT ????????									//
// ??? ???????????? ???? ??? ???????????(??) ??????????(?)				//
//======================================================================================//

find eip,#2C027212743D#		// ?????????? ?????
cmp $RESULT,0			// ????????
je @ERR_INIT_FAILED		// ???, ??????? ?????? ? ??????
bp $RESULT			// ???????! ?????? ???? ?? ???????? ?????
run				// ????????? ?????????
bc $RESULT			// ??????????? ? ??????? ????
cmp eip,$RESULT			// ????????? ????????? ?? ????????????
  jne @ERR_INIT_FAILED		// ???? ???, ??????? ?????? ? ??????
mov emule_swich,eip		//!??????????, ??????????? ? ???????? ???????
find eip,#FF6020#		// ?????? ???? ?????????? JMP DWORD PTR DS:[EAX+20]
cmp $RESULT,0			// ??????
je @ERR_INIT_FAILED		// ???, ??????? ?????? ? ??????
add eip,16			// ??????? ?? 16 ???? ?????? (??? ???????? JB SHORT ????????)
bp $RESULT			// ?????? ???? ?? ???????? ?????
run				// ????????? ?????????
bc $RESULT			// ??????????? ? ??????? ????
cmp eip,$RESULT			// ????????? ????????? ?? ????????????
  jne @ERR_INIT_FAILED		// ???? ???, ??????? ?????? ? ??????
mov emule_last_jamp,eax		// ???????? ???????? eax
add emule_last_jamp,20		// ...
mov emule_last_jamp,[emule_last_jamp]
mov eip,trace_call
bp emule_swich
run
bc emule_swich
add eip,43
@init_find_emule_type_jcc:
  mov temp,eip
  sti
  mov call_cur,[esp]
  mov addr_cur,call_cur
  sub call_cur,2
  cmp temp,call_cur
  jne @init_find_emule_type_jcc
bp addr_cur
run
bc addr_cur
mov emule_type_jcc,eip			//!!!!
find eip,#84C07417#
  cmp $RESULT,0
  je @ERR_INIT_FAILED
mov emule_jcc,$RESULT

mov eip,trace_call
bp emule_swich
run
bc emule_swich
add eip,90
@init_find_emule_cmp:
  mov temp,eip
  sti
  mov call_cur,[esp]
  mov addr_cur,call_cur
  sub call_cur,5
  cmp temp,call_cur
jne @init_find_emule_cmp
bp addr_cur
mov iter,0
@init_find_emule_cmp_get_arg1:
  mov temp,eip
  sti
  mov call_cur,[esp]
  mov addr_cur,call_cur
  sub call_cur,2
  cmp temp,call_cur
jne @init_find_emule_cmp_get_arg1
bp addr_cur
run
bc addr_cur
inc iter
cmp iter,2
jb @init_find_emule_cmp_get_arg1
mov emule_cmp_get_arg1,eip		//!!!!

mov iter,0
@init_find_emule_cmp_get_arg2:
  mov temp,eip
  sti
  mov call_cur,[esp]
  mov addr_cur,call_cur
  sub call_cur,5
  cmp temp,call_cur
  jne @init_arg1_ret
    bp addr_cur
    run
    bc addr_cur
  @init_arg1_ret:
  add call_cur,3
  cmp temp,call_cur
jne @init_find_emule_cmp_get_arg2
bp addr_cur
run
bc addr_cur
inc iter
cmp iter,2
jb @init_find_emule_cmp_get_arg2
mov emule_cmp_get_arg2,eip		//!!!!

@init_find_emule_type_cmp:
  mov temp,eip
  sti
  mov call_cur,[esp]
  mov addr_cur,call_cur
  sub call_cur,5
  cmp temp,call_cur
  jne @init_arg2_ret
    bp addr_cur
    run
    bc addr_cur
  @init_arg2_ret:
  add call_cur,3
  cmp temp,call_cur
jne @init_find_emule_type_cmp
bp addr_cur
run
bc addr_cur
sti
mov emule_type_cmp,eip			//!!!!
mov eax,4
run
bc eip

@init_find_emule_cmp_type_jcc:
  mov temp,eip
  sti
  mov call_cur,[esp]
  mov addr_cur,call_cur
  sub call_cur,2
  cmp temp,call_cur
jne @init_find_emule_cmp_type_jcc
bp addr_cur
run
bc addr_cur
mov emule_cmp_type_jcc,eip		//!!!!
find eip,#84C07417#
  cmp $RESULT,0
  je @ERR_INIT_FAILED
mov emule_cmp_jcc,$RESULT		//!!!!
mov eip,oep
bp oep
ai
bc oep
////////////////////////
mov addr_cur,eip
@find_empty_space:
  find addr_cur,#00000000000000000000000000#
    cmp $RESULT,0
    je @end
  mov table_of_jcc,$RESULT
  mov addr_cur,$RESULT
  mov temp,$RESULT
  add temp,1A
  find temp,#00000000000000000000000000#
    cmp $RESULT,0
    je @end
  mov addr_cur,$RESULT
  cmp temp,$RESULT
jne @find_empty_space
////////////////////////

mov scan_end,FFFFFFFF
ask "Enter new base of this code"
cmp $RESULT,0
je @ERR_INIT_FAILED
mov base_new, $RESULT //006D1000
jmp @init_skip
ret
////////////////////////
@init_hand:
mov oep,eip				// ????????? eip, ????? ????? ????????????
mov call_VM	   	,00C00000	// !????? ????? ??????????? ??????
mov scan_start	   	,00B70CA1	// !????????? ????? ???????????? (?????? VM ??????)
mov scan_end	   	,00B73FFE	// !?????????????? ????? ??????? ????????????
mov base_old	   	,00B70000	// !???? ????, ??? ????????????? ??????????? ????? ?????
mov base_new	   	,0049A000	// !???? ???????? ???? ??????, ??? ????? ????????????? ???
mov table_of_jcc   	,00B72A00	// !????? ?????? ??????? ??????, ???? ????? ?????? ?????????????? jcc
mov emule_swich	   	,00AA88DA	// !????? ??????? "SUB AL,2" ??? ??????????? ????? ???? ???????? (jmp,call,...)
mov emule_type_jcc 	,00AA892D	// !????? ????? ?????, ????????????? ??? ???????????? ??????
mov emule_jcc	   	,00AA893C	// !????? ??????? "TEST AL,AL" ??? jcc
mov emule_cmp_get_arg1	,00AA8786	// !????? ????? ?????, ????????????? - ?? ???????? ??? ?? ????????? ?????????? (????????1)
mov emule_cmp_get_arg2	,00AA87C2	// !????? ????? ?????, ????????????? - ?? ???????? ??? ?? ????????? ?????????? (????????2)
mov emule_type_cmp	,00AA8805	// !????? ????? ?????+3 (CMP EAX,4) ????????????? ??? ??????????? "CMP" 
mov emule_cmp_type_jcc	,00AA898D	// !????? ????? ?????, ????????????? ??? ???????????? ?????? (????? cmp) 
mov emule_cmp_jcc	,00AA899C	// !????? ??????? "TEST AL,AL" ??? jcc (????? CMP)

mov emule_last_jamp	,00C10000	// !????? ?????????? ??????, ??? ????????? "JMP DWORD PTR SS:[ESP-4]"
@init_skip:
find emule_last_jamp,#FF6424FC#
cmp $RESULT,0
je @ERR_EMULE_LAST_JAMP_NOT_FOUND
mov emule_last_jamp,$RESULT

eval "Find VM call at [{scan_start}..{scan_end}].."
mov Info,$RESULT
log Info

/////////////////////////////////////////////////////////////////////////////////////////////
//?????? ????????? ???????? ????? ??? ??????? AsProtect'? ??????????? ?????????? ??????????//
/////////////////////////////////////////////////////////////////////////////////////////////
@find_VM_call:			// ???? ?????? VM ??????
  cmp scan_start,scan_end	// ?????????, ?? ???????? ?? ??????? ????????????
  ja @end			// ???? ????????, ?? ??????????? ?????
  find scan_start,#E8#		// ???? ????? "call"
  cmp $RESULT,0			// ???? ?????? ?? ?????, ????????? ?????
  je @end
  mov addr_cur,$RESULT		// ???????? ????? ????????? ??????
  inc addr_cur			// ??????????? ?? ????, ????? ???????? ???????? ?? ????
  mov scan_start,addr_cur	// ????????????? ????????? ??????? ????????????, ??? ????????? ????????
  mov temp,[addr_cur]		// ???????? ???????? ?? ????
  add temp,addr_cur		// ????????? ?????????? ?????
  add temp,4			// ???????????? ???????????? ?????? ?????
  cmp temp,call_VM		// ?????????? ????? ????????? ????? ? ????????
  jne @find_VM_call		// ???? ?? ?????, ?????????? ?????
  dec addr_cur			// ???????????? ????????? ?? ????
  /////////[ DEBUG INFO ]/////////
  eval "Call found at {addr_cur}"
  mov Info,$RESULT
  log Info
  ////////////////////////////////
  mov eip,addr_cur		// ????????????? eip ?? ?????? VM ?????
  ////////////////////////////////
  cmp eip,00E41906
  jne @n
  //msg "pause!"
  @n:
  ////////////////////////////////
  jmp @rebuild_VM_call		// ??????? ? ????????? ?????????????? ??????
//end @find_VM_call
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
// ?????? ????????? ?????????? ??? ??????????? ???????, ? ? ??????????? //
// ?? ????? ??????? ?????????? ??????????????? ????????? ??????????????//
//////////////////////////////////////////////////////////////////////////
@rebuild_VM_call:
  sub addr_cur,5		// ????????? ?? 5 ???? ???? ?????? ?????
  mov temp,[addr_cur]		// ??????, ??? ??? ?????
  and temp,000000FF		// ??? ?????????? ????????? ?????? 1 ????, ????????? ??????????? 0
  cmp temp,00000068		// ?????????? ? ??????? 'PUSH'
  je @rebuild_push		// ???? ?????, ?????????? ????????????? ??? ????? ????
  add addr_cur,5		// ??????????????? ????????? ?? VM ????
 @trace_VM: 
  bp emule_swich		// ?????? ???? ?? ???? ??????????? ??????????? ???????
  run				// ????????? ?????????
  bc emule_swich		// ???????????, ??????? ????
  cmp eip,emule_swich		// ?????????, ????????? ?? ????????????
  jne @ERR_BP_AT_SWICH_NOT_WORK	// ???? ???, ?????????? ?????? ? ??????

  mov emule_type_jcc_temp,emule_type_jcc
  mov emule_jcc_temp,emule_jcc
  mov table_of_jcc_base,table_of_jcc

  mov temp,eax			// ???????? ??? ??????????? ???????
  cmp temp,0			// 0 - ???????? call
  je @trace_call_or_jmp		// ????????? ?? ?????????????? ?????
  cmp temp,1			// 1 - ???????? jmp
  je @trace_call_or_jmp		// ????????? ?? ?????????????? ??????
  cmp temp,2			// 2 - ???????? 1 ?? 16 ???????? ???????
  je @trace_jcc			// ????????? ?? ?????????????? jcc (jxx)
  cmp temp,3			// 3 - ???????? ????? 2? ??????? - cmp + jcc
  je @trace_cmp_and_jcc		// ????????? ?? ?????????????? cmp + jcc
  msg "[Error!] Unknown emule command!"	// ????? ???-?? ???? ?? ??? ??????? ??????
  jmp @find_VM_call		// ? ???? ????????? ????
//end @rebuild_VM_call
//////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////
// ?????? ????????? ?????????????? ???? ? ??????, ??????? //
// ????????? ? ??????? PUSH'? ? ???????? ?????? ????????  //
////////////////////////////////////////////////////////////
@rebuild_push:
  inc addr_cur				// ??????? ????????? ?? ?????
  mov temp,[addr_cur]			// ???????? ?????
  //////[ DEBUG INFO ]//////
  eval "found PUSH {temp}"		
  mov Info,$RESULT
  log Info
  //////////////////////////
  sub temp,base_old			// ???????? ?? ?????? ?????? ????
  add temp,base_new			// ?????????? ????? ????
  /////////[ DEBUG INFO ]//////////
  eval "converted to PUSH {temp}"
  mov Info,$RESULT
  log Info
  /////////////////////////////////
  mov [addr_cur],temp			// ????????? ?????????? ????? ?? ?????
  add addr_cur,4			// ???????????? ?????????
  jmp @trace_VM				// ??????? ?????, ? ????. ?????????????? ??????
//end @rebuild_push
////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
// ?????? ????????? ??????????????? ??????????? ??????? "jmp" ? "call"  //
//////////////////////////////////////////////////////////////////////////
@trace_call_or_jmp:			
  bp emule_last_jamp			// ?????? ???? ?? ????????? ????? VM
  run					// ????????? ?????????
  bc emule_last_jamp			// ????????????, ?????? ????	
  cmp eip,emule_last_jamp		// ?????????, ????????? ?? ??????????
  jne @ERR_BP_AT_EMULE_LAST_JAMP_NOT_WORK // ???? ???, ??????? ?????? ? ???????
  mov temp,esp				// ???????? ????????? ?? ????
  sub temp,4				// ??????????? ???? (esp-4)
  mov call_cur,[temp]			// ???????? ????? ????????
  /////[ DEBUG INFO ]/////
  eval "Recovering 'jmp {call_cur}'..." 
  mov Info,$RESULT
  log Info
  ////////////////////////
  mov temp,addr_cur			// ? ???? ?????? ????? ????????
  cmp call_cur,base_old			// ?????????, ??????? ??? ????? ??? ???
  jae @short_call			// ???? ???, ?? ?? ???????????????
    sub temp,base_old			// ???????? ?? ?????? ??????? ????
    add temp,base_new			// ? ?????????? ????, ??????? ????? ? ?????
  @short_call:
  sub call_cur,temp			// ???????? ?? ?????? ???????? ????? VM ?????
  sub call_cur,5			// ????????????
  /// Debug!!!
  mov eip,addr_cur
  ////////////////
  //[ ????????? ?????? call 00XX0000 -> jmp XXXXXXXX ]//
  mov [addr_cur],E9			
  inc addr_cur				 
  mov [addr_cur],call_cur
  //////////////////////////////////////////////////////
  jmp @find_VM_call
//end @trace_call_or_jmp
//////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
// ?????? ????????? ??????????????? ??????????? ??????? "jcc" (????? 16) //
///////////////////////////////////////////////////////////////////////////
@trace_jcc:
  bp emule_type_jcc_temp		// ?????? ???? ?? ???? ????????? ???? ????. ??????
  run					// ????????? ?????????
  bc emule_type_jcc_temp		// ???????????, ? ??????? ????
    cmp eip,emule_type_jcc_temp		// ?????????, ????????? ?? ????????????
    jne @ERR_BP_AT_EMULE_TYPE_JCC_NOT_WORK// ???? ???, ??????? ?????? ? ??????
  mov type_of_jcc,eax		// ????????? ??? ???????????? ??????
  bp emule_jcc_temp			// ?????? ???? ?? ???????? ??????
  run					// ????????? ?????????
  bc emule_jcc_temp			// ???????????, ??????? ?????
    cmp eip,emule_jcc_temp		// ????????? ????????? ?? ????????????
    jne @ERR_BP_AT_EMULE_JCC_NOT_WORK	// ???? ???, ??????? ?????? ? ??????
  mov eax,1				// ? eax ??????? ???????, ????? ???????? ????????
  bp emule_last_jamp			// ? ??????????? ?? ????, ??? ? ??? ??????????? ???????
  run					// ?????? ???? ?? ????????? ????? ????? ? ????????? ?????
  bc emule_last_jamp			// ??????????? ? ??????? ????
    cmp eip,emule_last_jamp		// ?????????, ????????? ?? ??????????
    jne @ERR_BP_AT_EMULE_LAST_JAMP_NOT_WORK // ???? ???, ??????? ?????? ? ???????
  mov temp,esp				// ???????? ????????? ?? ????
  sub temp,4				// ??????????? ???? (esp-4)
  mov call_cur,[temp]			// ???????? ????? ????????
  					//
  cmp call_cur,base_old			// ?????????, ??????? ??? ????? ??? ???
  jae @short_jcc			// ???? ???, ?????????? ??????????????
    mov temp,base_new			// ? ???? ????? ????
    sub temp,call_addr			// ???????? ?? ????? ???? ?????? ?????, ???????? ????????
    add temp,base_old			// ? ?????????? ? ???????? ?????? ????
    mov call_cur,temp			// ?????????????? ???????? ????
  @short_jcc:
    
//////////////////////////
// ?????? ???? ??????   //
//  ???? ???????????    //
//   ????? ?? ????      //
//////////////////////////
  cmp type_of_jcc,0	//
  mov temp,"jo"		//
  je @patch_table	//
//////////////////////////
  cmp type_of_jcc,1	//
  mov temp,"jno"	//
  je @patch_table	//
//////////////////////////
  cmp type_of_jcc,2	//
  mov temp,"jb"		//
  je @patch_table	//
//////////////////////////
  cmp type_of_jcc,3	//
  mov temp,"jnb"	//
  je @patch_table	//
//////////////////////////
  cmp type_of_jcc,4	//
  mov temp,"je"		//
  je @patch_table	//
//////////////////////////
  cmp type_of_jcc,5	//
  mov temp,"jnz"	//
  je @patch_table	//
//////////////////////////
  cmp type_of_jcc,6	//
  mov temp,"jpe"	//
  je @patch_table	//
//////////////////////////
  cmp type_of_jcc,7	//
  mov temp,"jpo"	//
  je @patch_table	//
//////////////////////////
  cmp type_of_jcc,8	//
  mov temp,"js"		//
  je @patch_table	//
//////////////////////////
  cmp type_of_jcc,9	//
  mov temp,"jns"	//
  je @patch_table	//
//////////////////////////
  cmp type_of_jcc,A	//
  mov temp,"jbe"	//
  je @patch_table	//
//////////////////////////
  cmp type_of_jcc,B	//
  mov temp,"ja"		//
  je @patch_table	//
//////////////////////////
  cmp type_of_jcc,C	//
  mov temp,"jl"		//
  je @patch_table	//
//////////////////////////
  cmp type_of_jcc,D	//
  mov temp,"jge"	//
  je @patch_table	//
//////////////////////////
  cmp type_of_jcc,E	//
  mov temp,"jle"	//
  je @patch_table	//
//////////////////////////
  cmp type_of_jcc,F	//
  mov temp,"jg"		//
  je @patch_table	//
//////////////////////////

  //////////////////////////////////////////////////////////////////////////
  // ???, ??? ??? ??????????? ?????? ???????? (2 ?????), ? ???? ???????   //
  // ????????? ????????? ???????? ??????, ?????????? ???????????????      //
  // ??? ?????? ? ????????????? ????????, ? ??? ????, ???????, ?????????  //
  // ??????? EVAL ? ???????? ?????? ???????????? ??????? ? ? ???????      //
  // ??????? ASM ? ????? OllyDbg ?????? ??????? ??? ?? ????. ???? ?? ???? //
  // ?? ??????? :)........................................................//
  //////////////////////////////////////////////////////////////////////////

  @patch_table:			
  eval "{temp} {call_cur}"
  asm table_of_jcc,$RESULT	// ????????? ???? ??????? ???????
  
  add table_of_jcc,6		// ?????? ?????????? ?????? = 6 ????
  mov eip,addr_cur		// ????? ?????? ?? VM ????, ????? ????? ?????? ??????

/////////////////////////////////////////////////
cmp emule_type_jcc_temp,emule_cmp_type_jcc
  jne @recover_jcc
////////////////////////
  bp emule_type_cmp
  run
  bc emule_type_cmp
    cmp eip,emule_type_cmp
    jne @ERR_BP_AT_EMULE_TYPE_CMP_NOT_WORK
  mov ebp,00400000
  add esp,10
  mov [esp],00400000
  sub esp,10
////////////////////////
  ////////////////////////////////////////////////////
 @recover_jcc:
  bp emule_jcc_temp			// ????? ?????? ???? ?? ???????? ??????
  run					// ????????? ?????????
  bc emule_jcc_temp			// ??????????? ??????? ????
  cmp eip,emule_jcc_temp		// ????????? ????????? ?? ????????????
  jne @ERR_BP_AT_EMULE_JCC_NOT_WORK	// ???? ??? ??????? ?????? ? ??????
  mov eax,0				// ? ??? 0, ????? ???????? ?????? ?????
  bp emule_last_jamp			// ?????? ???? ?? ????????? ????? ?????
  run					// ????????? ?????
  bc emule_last_jamp			// ??????????? ? ??????? ????
  cmp eip,emule_last_jamp		// ?????????, ????????? ?? ??????????
  jne @ERR_BP_AT_EMULE_LAST_JAMP_NOT_WORK // ???? ???, ??????? ?????? ? ???????
  mov temp,esp				// ???????? ????????? ?? ????
  sub temp,4				// ??????????? ???? (esp-4)
  mov call_cur,[temp]			// ???????? ????? ????????

  cmp call_cur,base_old			// ?????????, ??????? ??? ????? ??? ???
  jae @short_jmp			// ???? ???, ?????????? ??????????????
    mov temp,base_new			// ? ???? ????? ????
    sub temp,call_addr			// ???????? ?? ????? ????, ???????? ?????
    add temp,base_old			// ? ?????????? ????????? ???????? ? ?????? ????
    mov call_cur,temp			// ?????????????? ???????? ????? ??????????????
  @short_jmp:
  eval "jmp {call_cur}"			// ????????? ?????? ???????????? ???????
  asm table_of_jcc,$RESULT		// ???????????? ?????????? (????????? ??????????)
  
  /// Debug!!!
  mov eip,addr_cur
  /////////////
  mov temp,table_of_jcc_base		// ???????? ??????? ???????? ? ??????? ?????????
  sub temp,addr_cur			// ????????? ???????? ???????????? VM ?????
  sub temp,5				// ?????????????
  mov [addr_cur],E9			// ?????? call VM ????????? jmp
  inc addr_cur				// ?????? ?? ???????? VM
  mov [addr_cur],temp			// ????????? ?????? VM ???????? ????? ????. ?????????
  dec addr_cur				// \ ???????????????
  add table_of_jcc,5			// / ?????????
  //////////////////////////////////////////////////////
jmp @find_VM_call
//end @trace_jcc
//////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
// ????????? ??????????????? ??????????? ??????? ????????? (CMP) ????? 5 //
///////////////////////////////////////////////////////////////////////////
@trace_cmp_and_jcc:
  
  mov table_of_jcc_base,table_of_jcc		// ?????????? ??????? ???? ??????? ?????????
  bp emule_cmp_get_arg1				// ?????? ???? ????? ?????, ???????????? ?????? ???????? ?????????
  run						// ????????? ?????????
  bc emule_cmp_get_arg1				// ????????? ? ??????? ????
   cmp eip,emule_cmp_get_arg1			// ?????????, ????????? ?? ????????????
   jne @ERR_BP_AT_EMULE_CMP_GET_ARG1_NOT_WORK	// ???? ???, ??????? ?????? ? ??????
  mov arg1_num,eax				// ?????????? ?????? ????????
		
  bp emule_cmp_get_arg2				// ?????? ???? ????? ?????, ???????????? ?????? ???????? ?????????
  run						// ????????? ?????????
  bc emule_cmp_get_arg2				// ????????? ? ??????? ????
   cmp eip,emule_cmp_get_arg2			// ?????????, ????????? ?? ????????????
   jne @ERR_BP_AT_EMULE_CMP_GET_ARG1_NOT_WORK	// ???? ???, ??????? ?????? ? ??????
  mov arg2_num,eax				// ?????????? ?????? ????????
  bp emule_type_cmp				// ?????? ???? ?? ???????? ???? ?????????
  run						// ????????? ?????????
  bc emule_type_cmp				// ????????? ? ??????? ????
    cmp eip,emule_type_cmp			// ?????????, ????????? ?? ????????????
    jne @ERR_BP_AT_EMULE_TYPE_CMP_NOT_WORK	// ???? ???, ??????? ?????? ? ??????
  mov type_of_cmp,eax				// ?????????? ??? CMP

 // CMP DWORD PTR DS:[????????],????????
 @case0:
  cmp type_of_cmp,0
  jne @case1
  mov str1,"cmp dword ptr ds:["  
  mov str2,"],"
  mov str3,""

  mov arg1_display,"eax"
  mov emule_cmp_size,2
  cmp arg1_num,0
  je  @0_calc_arg2

  mov arg1_display,"ecx"
  mov emule_cmp_size,2
  cmp arg1_num,1
  je  @0_calc_arg2

  mov arg1_display,"edx"
  mov emule_cmp_size,2
  cmp arg1_num,2
  je  @0_calc_arg2

  mov arg1_display,"ebx"
  mov emule_cmp_size,2
  cmp arg1_num,3
  je  @0_calc_arg2

  mov arg1_display,"esp"
  mov emule_cmp_size,3
  cmp arg1_num,4
  je  @0_calc_arg2

  mov arg1_display,"ebp"
  mov emule_cmp_size,3
  cmp arg1_num,5
  je  @0_calc_arg2

  mov arg1_display,"esi"
  mov emule_cmp_size,2
  cmp arg1_num,6
  je  @0_calc_arg2
  
  mov arg1_display,"edi"
  mov emule_cmp_size,2
  cmp arg1_num,7
  je  @0_calc_arg2

  mov arg1_display,ebp
  mov emule_cmp_size,6
 @0_calc_arg2:
  mov arg2_display,"eax"
  cmp arg2_num,0
  je  @end_switch
  
  mov arg2_display,"ecx"
  cmp arg2_num,1
  je  @end_switch

  mov arg2_display,"edx"
  cmp arg2_num,2
  je  @end_switch

  mov arg2_display,"ebx"
  cmp arg2_num,3
  je  @end_switch

  mov arg2_display,"esp"
  inc emule_cmp_size
  cmp arg2_num,4
  je  @end_switch
  dec emule_cmp_size

  mov arg2_display,"ebp"
  inc emule_cmp_size
  cmp arg2_num,5
  je  @end_switch
  dec emule_cmp_size

  mov arg2_display,"esi"
  cmp arg2_num,6
  je  @end_switch

  mov arg2_display,"edi"
  cmp arg2_num,7
  je  @end_switch

  mov arg2_display,esp
  add arg2_display,10
  mov arg2_display,[arg2_display]
  add emule_cmp_size,4
 
  jmp @end_switch
 // CMP ????????,DWORD PTR DS:[????????]
 @case1:  
  cmp type_of_cmp,1
  jne @case2
  mov str1,"cmp "  
  mov str2,",dword ptr ds:["
  mov str3,"]"

  mov arg1_display,"eax"
  mov emule_cmp_size,2
  cmp arg1_num,0
  je  @1_calc_arg2

  mov arg1_display,"ecx"
  mov emule_cmp_size,2
  cmp arg1_num,1
  je  @1_calc_arg2

  mov arg1_display,"edx"
  mov emule_cmp_size,2
  cmp arg1_num,2
  je  @1_calc_arg2

  mov arg1_display,"ebx"
  mov emule_cmp_size,2
  cmp arg1_num,3
  je  @1_calc_arg2

  mov arg1_display,"esp"
  mov emule_cmp_size,2
  cmp arg1_num,4
  je  @1_calc_arg2

  mov arg1_display,"ebp"
  mov emule_cmp_size,2
  cmp arg1_num,5
  je  @1_calc_arg2

  mov arg1_display,"esi"
  mov emule_cmp_size,2
  cmp arg1_num,6
  je  @1_calc_arg2
  
  mov arg1_display,"edi"
  mov emule_cmp_size,2
  cmp arg1_num,7
  je  @1_calc_arg2

  mov arg1_display,ebp
  mov emule_cmp_size,6
 @1_calc_arg2:
  mov arg2_display,"eax"
  cmp arg2_num,0
  je  @end_switch
  
  mov arg2_display,"ecx"
  cmp arg2_num,1
  je  @end_switch

  mov arg2_display,"edx"
  cmp arg2_num,2
  je  @end_switch

  mov arg2_display,"ebx"
  cmp arg2_num,3
  je  @end_switch

  mov arg2_display,"esp"
  cmp arg2_num,4
  je  @end_switch
  
  mov arg2_display,"ebp"
  cmp arg2_num,5
  je  @end_switch
  
  mov arg2_display,"esi"
  cmp arg2_num,6
  je  @end_switch

  mov arg2_display,"edi"
  cmp arg2_num,7
  je  @end_switch

  mov arg2_display,esp
  add arg2_display,10
  mov arg2_display,[arg2_display]
  add emule_cmp_size,4
  jmp @end_switch
  // CMP BYTE PTR DS:[????????],??
 @case2:
  cmp type_of_cmp,2
  jne @case3
  mov str1,"cmp byte ptr ds:["  
  mov str2,"],"
  mov str3,""

  mov arg1_display,"eax"
  mov emule_cmp_size,2
  cmp arg1_num,0
  je  @2_calc_arg2

  mov arg1_display,"ecx"
  mov emule_cmp_size,2
  cmp arg1_num,1
  je  @2_calc_arg2

  mov arg1_display,"edx"
  mov emule_cmp_size,2
  cmp arg1_num,2
  je  @2_calc_arg2

  mov arg1_display,"ebx"
  mov emule_cmp_size,2
  cmp arg1_num,3
  je  @2_calc_arg2

  mov arg1_display,"esp"
  mov emule_cmp_size,4
  cmp arg1_num,4
  je  @2_calc_arg2

  mov arg1_display,"ebp"
  mov emule_cmp_size,4
  cmp arg1_num,5
  je  @2_calc_arg2

  mov arg1_display,"esi"
  mov emule_cmp_size,2
  cmp arg1_num,6
  je  @2_calc_arg2
  
  mov arg1_display,"edi"
  mov emule_cmp_size,2
  cmp arg1_num,7
  je  @2_calc_arg2

  mov arg1_display,ebp
  mov emule_cmp_size,6
 @2_calc_arg2:
  mov arg2_display,"al"
  cmp arg2_num,0
  je  @end_switch
  
  mov arg2_display,"cl"
  cmp arg2_num,1
  je  @end_switch

  mov arg2_display,"dl"
  cmp arg2_num,2
  je  @end_switch

  mov arg2_display,"bl"
  cmp arg2_num,3
  je  @end_switch

  mov arg2_display,"??"
  cmp arg2_num,4
  je  @ERR_EMULE_ARG
  
  mov arg2_display,"??"
  cmp arg2_num,5
  je  @ERR_EMULE_ARG
  
  mov arg2_display,"??"
  cmp arg2_num,6
  je  @ERR_EMULE_ARG

  mov arg2_display,"??"
  cmp arg2_num,7
  je  @ERR_EMULE_ARG

  mov arg2_display,esp
  add arg2_display,10
  mov arg2_display,[arg2_display]
  add emule_cmp_size,1
  jmp @end_switch
  // CMP ??,BYTE PTR DS:[????????]
 @case3:
  cmp type_of_cmp,3
  jne @case4
  mov str1,"cmp "  
  mov str2,",byte ptr ds:["
  mov str3,"]"

  mov arg1_display,"al"
  mov emule_cmp_size,2
  cmp arg1_num,0
  je  @3_calc_arg2

  mov arg1_display,"cl"
  mov emule_cmp_size,2
  cmp arg1_num,1
  je  @3_calc_arg2

  mov arg1_display,"dl"
  mov emule_cmp_size,2
  cmp arg1_num,2
  je  @3_calc_arg2

  mov arg1_display,"bl"
  mov emule_cmp_size,2
  cmp arg1_num,3
  je  @3_calc_arg2

  mov arg1_display,"??"
  mov emule_cmp_size,2
  cmp arg1_num,4
  je  @3_calc_arg2

  mov arg1_display,"??"
  mov emule_cmp_size,2
  cmp arg1_num,5
  je  @3_calc_arg2

  mov arg1_display,"??"
  mov emule_cmp_size,2
  cmp arg1_num,6
  je  @3_calc_arg2
  
  mov arg1_display,"??"
  mov emule_cmp_size,2
  cmp arg1_num,7
  je  @3_calc_arg2

  mov arg1_display,ebp
  mov emule_cmp_size,6
 @3_calc_arg2:
  mov arg2_display,"eax"
  cmp arg2_num,0
  je  @end_switch
  
  mov arg2_display,"ecx"
  cmp arg2_num,1
  je  @end_switch

  mov arg2_display,"edx"
  cmp arg2_num,2
  je  @end_switch

  mov arg2_display,"ebx"
  cmp arg2_num,3
  je  @end_switch

  mov arg2_display,"esp"
  cmp arg2_num,4
  je  @end_switch
  
  mov arg2_display,"ebp"
  cmp arg2_num,5
  je  @end_switch
  
  mov arg2_display,"esi"
  cmp arg2_num,6
  je  @end_switch

  mov arg2_display,"edi"
  cmp arg2_num,7
  je  @end_switch

  mov arg2_display,esp
  add arg2_display,10
  mov arg2_display,[arg2_display]
  add emule_cmp_size,1
  jmp @end_switch
  // CMP ????????,????????
 @case4:
  cmp type_of_cmp,4
  jne @ERR_UNKNOWN_TYPE_CMP
  mov str1,"cmp "  
  mov str2,","
  mov str3,""

  mov arg1_display,"eax"
  mov emule_cmp_size,2
  cmp arg1_num,0
  je  @4_calc_arg2

  mov arg1_display,"ecx"
  mov emule_cmp_size,2
  cmp arg1_num,1
  je  @4_calc_arg2

  mov arg1_display,"edx"
  mov emule_cmp_size,2
  cmp arg1_num,2
  je  @4_calc_arg2

  mov arg1_display,"ebx"
  mov emule_cmp_size,2
  cmp arg1_num,3
  je  @4_calc_arg2

  mov arg1_display,"esp"
  mov emule_cmp_size,2
  cmp arg1_num,4
  je  @4_calc_arg2

  mov arg1_display,"ebp"
  mov emule_cmp_size,2
  cmp arg1_num,5
  je  @4_calc_arg2

  mov arg1_display,"esi"
  mov emule_cmp_size,2
  cmp arg1_num,6
  je  @4_calc_arg2
  
  mov arg1_display,"edi"
  mov emule_cmp_size,2
  cmp arg1_num,7
  je  @4_calc_arg2

  mov arg1_display,ebp
  mov emule_cmp_size,5
 @4_calc_arg2:
  mov arg2_display,"eax"
  cmp arg2_num,0
  je  @end_switch
  
  mov arg2_display,"ecx"
  cmp arg2_num,1
  je  @end_switch

  mov arg2_display,"edx"
  cmp arg2_num,2
  je  @end_switch

  mov arg2_display,"ebx"
  cmp arg2_num,3
  je  @end_switch

  mov arg2_display,"esp"
  cmp arg2_num,4
  je  @end_switch
  
  mov arg2_display,"ebp"
  cmp arg2_num,5
  je  @end_switch
  
  mov arg2_display,"esi"
  cmp arg2_num,6
  je  @end_switch

  mov arg2_display,"edi"
  cmp arg2_num,7
  je  @end_switch

  mov arg2_display,esp
  add arg2_display,10
  mov arg2_display,[arg2_display]
  add emule_cmp_size,4
 
  jmp @end_switch
//////////////////////////////////////////////////////////////////////////////////////
 @end_switch:
  eval "{str1}{arg1_display}{str2}{arg2_display}{str3}"
  asm table_of_jcc,$RESULT
  add table_of_jcc,emule_cmp_size
  ///////////////
  mov ebp,00400000
  add esp,10
  mov [esp],00400000
  sub esp,10
  
  mov emule_type_jcc_temp,emule_cmp_type_jcc
  mov emule_jcc_temp,emule_cmp_jcc
  jmp @trace_jcc
  ///////////////
  pause  

@end:
mov eip,oep
log "____________________________________"
ret

@ERR_BP_AT_SWICH_NOT_WORK:
msg "[Error!] BreakPoint at emule_swich not work!"
jmp @end

@ERR_BP_AT_EMULE_LAST_JAMP_NOT_WORK:
msg "[Error!] BreakPoint at emule_last_jamp not work!"
jmp @end

@ERR_BP_AT_EMULE_TYPE_JCC_NOT_WORK:
msg "[Error!] BreakPoint at emule_type_jcc not work!"
jmp @end

@ERR_BP_AT_EMULE_JCC_NOT_WORK:
msg "[Error!] BreakPoint at emule_jcc not work!"
jmp @end

@ERR_BP_AT_EMULE_CMP_GET_ARG1_NOT_WORK:
msg "[Error!] BreakPoint at emule_cmp_get_argX not work!"
jmp @end

@ERR_BP_AT_EMULE_TYPE_CMP_NOT_WORK:
msg "[Error!] BreakPoint at emule_type_cmp not work!"
jmp @end

@ERR_BP_AT_EMULE_CMP_NOT_WORK:
msg "[Error!] BreakPoint at emule_cmp not work!"
jmp @end

@ERR_BP_AT_EMULE_CMP_TYPE_JCC_NOT_WORK:
msg "[Error!] BreakPoint at emule_cmp_type_jcc not work!"
jmp @end

@ERR_EMULE_LAST_JAMP_NOT_FOUND:
msg "[Error!] Command 'JMP DWORD PTR SS:[ESP-4]' not found!"
jmp @end

@ERR_VM_CALL_NOT_FOUND:
msg "[Error!] VM call not found!"
jmp @end

@ERR_INIT_FAILED:
msg "[Error!] Init failed!"
jmp @end

@ERR_EMULE_ARG:
msg "[Error!] Register not found!"
jmp @end

@ERR_UNKNOWN_TYPE_CMP:
msg "[Error!] Unknown type of cmp instruction!"
jmp @end